package app.util.image.action
{
	import flash.filters.ColorMatrixFilter;
	
	public class ColorMatrix
	{		
		//A standard for converting RGB values to Luminance. By Paul Haeberli.
		public static const R_LUM:Number = 0.3086;
		public static const G_LUM:Number = 0.6094;
		public static const B_LUM:Number = 0.0820;

		public static const IDENTITY:Array = [1,0,0,0,0,
											 0,1,0,0,0,
											 0,0,1,0,0,
											 0,0,0,1,0];
		
		public var matrix:Array;
	
		public function ColorMatrix()
		{
			this.reload();
		}
		
		public function adjustSaturation(s:Number):void
		{
			if(s == 0) return;
			
			var s:Number = (s + 100) / 100;
			
		    var irlum:Number = (1 - s) * R_LUM;
			var iglum:Number = (1 - s) * G_LUM;
			var iblum:Number = (1 - s) * B_LUM;
			
			var mat:Array =  [irlum + s, iglum    , iblum    , 0, 0,
						  	  irlum    , iglum + s, iblum    , 0, 0,
						   	  irlum    , iglum    , iblum + s, 0, 0,
						   	  0        , 0        , 0        , 1, 0 ];		
			multiplyMatrix(mat);
		}
		
		public function adjustHue(h:Number):void
		{
			if(h == 0) return;	
			
			h = h / 180 * Math.PI;
			var cosVal:Number = Math.cos(h);
			var sinVal:Number = Math.sin(h);
			var lumR:Number = 0.213;
			var lumG:Number = 0.715;
			var lumB:Number = 0.072;
			multiplyMatrix([
				lumR+cosVal*(1-lumR)+sinVal*(-lumR),lumG+cosVal*(-lumG)+sinVal*(-lumG),lumB+cosVal*(-lumB)+sinVal*(1-lumB),0,0,
				lumR+cosVal*(-lumR)+sinVal*(0.143),lumG+cosVal*(1-lumG)+sinVal*(0.140),lumB+cosVal*(-lumB)+sinVal*(-0.283),0,0,
				lumR+cosVal*(-lumR)+sinVal*(-(1-lumR)),lumG+cosVal*(-lumG)+sinVal*(lumG),lumB+cosVal*(1-lumB)+sinVal*(lumB),0,0,
				0,0,0,1,0,
				0,0,0,0,1
			]);			
		}	
		
		public function adjustContrast(value:Number):void
		{
			if(value == 0) return;
			
			value = (value + 100) / 100;
			var mat:Array = [value, 0    , 0    , 0, 128 * (1 - value),
						 	 0    , value, 0    , 0, 128 * (1 - value),
						 	 0    , 0    , value, 0, 128 * (1 - value),
							 0    , 0    , 0    , 1, 0];					
			multiplyMatrix(mat);
		}
		
		public function adjustBrightness(value:Number):void
		{
			if(value == 0) return;			
			
			var mat:Array = [1, 0, 0, 0, value,
						 	 0, 1, 0, 0, value,
							 0, 0, 1, 0, value,
				     		 0, 0, 0, 1, 0 ];	 		
			multiplyMatrix(mat);		
		}

		public function reload():void
		{
			matrix = IDENTITY.concat();
		}

		private function multiplyMatrix(mat:Array):void
		{		
			var temp:Array = new Array(20);
			var i:Number = 0;		
			for (var y:Number = 0; y < 4; y++ )
			{			
				for (var x:Number = 0; x < 5; x++ )
				{
					temp[i + x] = mat[i] * matrix[x] + 
								  mat[i + 1] * matrix[x +  5] + 
								  mat[i + 2] * matrix[x + 10] + 
								  mat[i + 3] * matrix[x + 15] +
								  (x == 4 ? mat[i + 4] : 0);
				}
				i += 5;
			}
			
			matrix = temp;		
		}
		 public function setChannels( r:int = 1, g:int = 2, b:int = 4, a:int = 8 ):void 
         { 
            var rf:Number = ((((((r & 1) == 1)) ? 1 : 0 + (((r & 2) == 2)) ? 1 : 0) + (((r & 4) == 4)) ? 1 : 0) + (((r & 8) == 8)) ? 1 : 0); 
             if (rf > 0){ 
                 rf = (1 / rf); 
             }; 
             var gf:Number = ((((((g & 1) == 1)) ? 1 : 0 + (((g & 2) == 2)) ? 1 : 0) + (((g & 4) == 4)) ? 1 : 0) + (((g & 8) == 8)) ? 1 : 0); 
             if (gf > 0){ 
                 gf = (1 / gf); 
             }; 
             var bf:Number = ((((((b & 1) == 1)) ? 1 : 0 + (((b & 2) == 2)) ? 1 : 0) + (((b & 4) == 4)) ? 1 : 0) + (((b & 8) == 8)) ? 1 : 0); 
             if (bf > 0){ 
                 bf = (1 / bf); 
             }; 
             var af:Number = ((((((a & 1) == 1)) ? 1 : 0 + (((a & 2) == 2)) ? 1 : 0) + (((a & 4) == 4)) ? 1 : 0) + (((a & 8) == 8)) ? 1 : 0); 
             if (af > 0){ 
                 af = (1 / af); 
             }; 
             this.multiplyMatrix([(((r & 1) == 1)) ? rf : 0, (((r & 2) == 2)) ? rf : 0, (((r & 4) == 4)) ? rf : 0, (((r & 8) == 8)) ? rf : 0, 0, (((g & 1) == 1)) ? gf : 0, (((g & 2) == 2)) ? gf : 0, (((g & 4) == 4)) ? gf : 0, (((g & 8) == 8)) ? gf : 0, 0, (((b & 1) == 1)) ? bf : 0, (((b & 2) == 2)) ? bf : 0, (((b & 4) == 4)) ? bf : 0, (((b & 8) == 8)) ? bf : 0, 0, (((a & 1) == 1)) ? af : 0, (((a & 2) == 2)) ? af : 0, (((a & 4) == 4)) ? af : 0, (((a & 8) == 8)) ? af : 0, 0]); 
         } 
 			
	}
}
